package imachine.engine;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

class Action {
	static Action createAction(int id, Object listener, String actionName) {
		Action action = null;
		if (null != listener && null != actionName) {
			Method method = null;
			try {
				method = listener.getClass().getMethod(actionName, PARAM_TYPES);
				if (Modifier.isPublic(method.getModifiers())) {
					action = new Action(id, listener, method);
				}
			} catch (SecurityException e) {
				//e.printStackTrace();
			} catch (NoSuchMethodException e) {
				//e.printStackTrace();
			}
		}
		return action;
	}

	final int id;
	final Object listener;
	final Method callbackMethod;

	private Action(int id, Object listener, Method callbackFunc) {
		this.id = id;
		this.listener = listener;
		this.callbackMethod = callbackFunc;
	}

	void perform(final Object inContext, Object outContext) {
		Object args[] = { id, inContext, outContext };
		try {
			callbackMethod.invoke(listener, args);
		} catch (IllegalArgumentException e) {
			// Shall not reach here
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// Shall not reach here
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO should we handle InvocationTargetException here?
			e.printStackTrace();
		}
	}

	private static final Class PARAM_TYPES[] = { Integer.class, Object.class,
			Object.class };

}
